/* Copyright (c) 2024 Huawei Technologies Co., Ltd.
openFuyao is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
import BreadCrumbCom from '@/components/BreadCrumbCom';
import { SyncOutlined, MoreOutlined, CloseOutlined, QuestionCircleOutlined, CheckOutlined, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons';
import { Form, Table, ConfigProvider, Space, Input, Button, Popover, message, Switch, Modal, Checkbox, Row, Col, Tag, Tooltip } from 'antd';
import zhCN from 'antd/es/locale/zh_CN';
import { useEffect, useState, useCallback } from 'openinula';
import '@/styles/ColocationWorkloadManagementPage.less';
import { sorterFirstAlphabet, firstAlphabetUp, compareIPs } from '@/tools/utils';
import ToolTipComponent from '@/components/ToolTipComponent';
import { getNodeListData, modifyColocationStatus, modifyNodeConfig } from '@/api/colocationApi';
import { ResponseCode, nodeStatus } from '@/common/constants';

const FeatureTag = ({ label, value }) => (
  <Tag className="feature-support-tag" color={value === 'OK' ? '#09aa71' : '#e7434a'}>
    {label}
    {value === 'OK' ? <CheckCircleFilled /> : <><CloseCircleFilled /><span className='falseTips'>{value}</span></>}
  </Tag>
);

export default function ColocationConfigurationPage() {
  const [configForm] = Form.useForm();
  const [isShow, setIsShow] = useState('');
  const [filterNodeStatus, setFilterNodeStatus] = useState([]);
  const [configLoading, setConfigLoading] = useState(false);
  const [isParamModalOpen, setIsParamModalOpen] = useState(false);
  // 节点信息
  const [colocationConfig, setColocationConfig] = useState({});
  const [configList, setConfigList] = useState([]);
  const [originalList, setOriginalList] = useState([]);
  // 表格分页
  const [configPage, setConfigPage] = useState(1);
  const [configPageSize, setConfigPageSize] = useState(10);

  const [messageApi, contextHolder] = message.useMessage();

  // 策略配置子表单
  const [volcanoSchedulerForm] = Form.useForm();
  const [quotaTurboForm] = Form.useForm();
  const [dynMemoryForm] = Form.useForm();
  const [dynCacheForm] = Form.useForm();
  const [psiForm] = Form.useForm();
  const [rubikForm] = Form.useForm();
  // 策略配置表单启用状态
  const [quotaTurboDisable, setQuotaTurboDisable] = useState(false);
  const [dynMemoryDisable, setDynmemoryDisable] = useState(false);
  const [dynCacheDisable, setDyncacheDisable] = useState(false);
  const [psiDisable, setPsiDisable] = useState(false);
  const [quotaTurboDisableMsg, setQuotaTurboDisableMsg] = useState('');
  const [dynMemoryDisableMsg, setDynmemoryDisableMsg] = useState('');
  const [dynCacheDisableMsg, setDyncacheDisableMsg] = useState('');
  const [psiDisableMsg, setPsiDisableMsg] = useState('');

  const enabledThreshold = Form.useWatch('enabledThreshold', volcanoSchedulerForm);
  const rubikThreshold = Form.useWatch('enabledThreshold', rubikForm);
  const quotaTurboThreshold = Form.useWatch('enabledThreshold', quotaTurboForm);
  const dynMemoryThreshold = Form.useWatch('enabledThreshold', dynMemoryForm);
  const dynCacheThreshold = Form.useWatch('enabledThreshold', dynCacheForm);
  const psiThreshold = Form.useWatch('enabledThreshold', psiForm);
  const [volcanoCheck, setVolcanoCheck] = useState(false);
  const handleConfigShowChange = () => {
    setIsShow('cant_show');
  };

  const searchNode = (totalData = originalList, isChange = true) => {
    const nodeConfigName = configForm.getFieldValue('nodeConfigName');
    let temporyList = totalData;
    if (nodeConfigName) {
      temporyList = temporyList.filter(item => (item.name).toLowerCase().includes(nodeConfigName.toLowerCase()));
    }
    setConfigList([...temporyList]);
    isChange ? setConfigPage(1) : null;
  };

  const handleRerfesh = async () => {
    getConfigList();
  };

  const handleOpenParamModal = () => {
    setIsParamModalOpen(true);
  };

  // 判断节点混部是否禁用，并生成禁用提示
  const isNodeSwitchDisabled = (record) => {
    const { featureSupport } = record;
    const notFulfillOption = (quotaTurboForm.getFieldValue('enabledThreshold') && featureSupport.quotaTurbo !== 'OK') ||
      (dynMemoryForm.getFieldValue('enabledThreshold') && featureSupport.dynMemory !== 'OK') ||
      (dynCacheForm.getFieldValue('enabledThreshold') && featureSupport.dynCache !== 'OK') ||
      (psiForm.getFieldValue('enabledThreshold') && featureSupport.psiDetection !== 'OK')
    if (featureSupport.cpuPreemption !== 'OK' || featureSupport.memoryPreemption !== 'OK') return true;
    if (notFulfillOption) return true;
    return false;
  };
  const getNodeSwitchDisableMsg = (record) => {
    const { featureSupport } = record;
    let arr = [];
    if (featureSupport.cpuPreemption !== 'OK' || featureSupport.memoryPreemption !== 'OK') {
      if (featureSupport.cpuPreemption !== 'OK') { arr.push('cpuPreemption') };
      if (featureSupport.memoryPreemption !== 'OK') { arr.push('memoryPreemption') };
      return `节点未支持必要特性：${arr.join(', ')}`;
    }
    arr = [];
    if (quotaTurboForm.getFieldValue('enabledThreshold') && featureSupport.quotaTurbo !== 'OK') { arr.push('quotaTurbo') };
    if (dynMemoryForm.getFieldValue('enabledThreshold') && featureSupport.dynMemory !== 'OK') { arr.push('dynMemory') };
    if (psiForm.getFieldValue('enabledThreshold') && featureSupport.psiDetection !== 'OK') { arr.push('psiDetection') };
    if (dynCacheForm.getFieldValue('enabledThreshold') && featureSupport.dynCache !== 'OK') { arr.push('dynCache') };
    if (arr.length > 0) return `节点未支持启用中的高级特性：${arr.join(', ')}`;
    return '';
  };

  const DisabledTipSwitch = ({ disabled, disableMsg, ...props }) => {
    // 判断是否禁用
    if (disabled) {
      return (
        <Tooltip title={disableMsg}>
          <span>
            <Switch disabled {...props} />
          </span>
        </Tooltip>
      );
    }
    return <Switch {...props} />;
  };

  const configColumns = [
    {
      title: '节点名称',
      key: 'nodeConfigName',
      sorter: (a, b) => sorterFirstAlphabet(a.name, b.name),
      render: (_, record) => record.name,
    },
    Table.EXPAND_COLUMN,
    {
      title: '混部能力支持',
      key: 'operator',
      render: (_, record) => {
        if (record.featureSupport.cpuPreemption === 'OK' && record.featureSupport.memoryPreemption === 'OK') {
          const supportOptionFeatures = record.featureSupport.quotaTurbo === 'OK' &&
            record.featureSupport.dynCache === 'OK' &&
            record.featureSupport.dynMemory === 'OK' &&
            record.featureSupport.psiDetection === 'OK'
          if (supportOptionFeatures) {
            return '全面支持';
          } else {
            return '部分支持';
          }
        } else {
          return '不可用';
        }
      },
    },
    {
      title: '状态',
      key: 'status',
      filters: filterNodeStatus,
      filterMultiple: false,
      onFilter: (value, record) => record.status.toLowerCase() === value.toLowerCase(),
      sorter: (a, b) => sorterFirstAlphabet(a.status, b.status),
      render: (_, record) => <p
        className={`resource_status ${(record.status).toLowerCase()}_circle`}>
        {firstAlphabetUp(record.status)}
      </p>,
    },
    {
      title: 'IP地址',
      key: 'ip',
      sorter: (a, b) => compareIPs(a.addresses, b.addresses),
      render: (_, record) => <>
        {record?.addresses ? record.addresses.map(item => {
          return <div className='table_tuning_box'><p>{item || '--'}</p></div>;
        }) : '--'}
      </>,
    },
    {
      title: 'OS版本',
      key: 'os_version',
      sorter: (a, b) => sorterFirstAlphabet(a.osImage, b.osImage),
      render: (_, record) => record.osImage || '--',
    },
    {
      title: '开启混部节点',
      key: 'is_open',
      sorter: (a, b) => sorterFirstAlphabet(a.isColocated, b.isColocated),
      render: (_, record) => <DisabledTipSwitch
        checked={record.isColocated}
        onChange={(checked) => handleControlNode(checked, record.name)}
        disabled={isNodeSwitchDisabled(record)}
        disableMsg={getNodeSwitchDisableMsg(record)}
      />,
    },
  ];

  const handleControlNode = async (checked, name) => {
    try {
      const res = await modifyColocationStatus(name, checked);
      if (res.status === ResponseCode.OK) {
        messageApi.success(`节点${name}${checked ? '已开启' : '已关闭'}混部功能`);
        // 更新数据
        getConfigList(false);
      }
    } catch (e) {
      if (e) {
        messageApi.error(`修改节点${name}混部状态失败，${e.response.data.message}`);
      }
    }
  };

  const handleParamOk = async () => {
    try {
      await volcanoSchedulerForm.validateFields();
      await rubikForm.validateFields();
      await quotaTurboForm.validateFields();
      await dynMemoryForm.validateFields();
      await dynCacheForm.validateFields();
      await psiForm.validateFields();
    } catch {
      messageApi.error("混部配置参数校验失败");
      return;
    }

    const eviction = rubikThreshold ? {
      enable: rubikThreshold,
      cpuEvict: {
        threshold: Number(rubikForm.getFieldValue('cpuEvict')) || 0,
      },
      memoryEvict: {
        threshold: Number(rubikForm.getFieldValue('memoryEvict')) || 0,
      },
    } : {
      enable: false,
    };
    const quotaTurbo = quotaTurboThreshold ? {
      enable: quotaTurboThreshold,
      highWaterMark: Number(quotaTurboForm.getFieldValue('highWaterMark')) || 0,
      alarmWaterMark: Number(quotaTurboForm.getFieldValue('alarmWaterMark')) || 0,
    } : {
      enable: false,
    };
    const dynMemory = { enable: dynMemoryThreshold };
    const dynCache = dynCacheThreshold ? {
      enable: dynCacheThreshold,
      membandPercent: {
        low: Number(dynCacheForm.getFieldValue('memBandLow')) || 0,
        mid: Number(dynCacheForm.getFieldValue('memBandMid')) || 0,
        high: Number(dynCacheForm.getFieldValue('memBandHigh')) || 0,
      },
      l3Percent: {
        low: Number(dynCacheForm.getFieldValue('l3PercentLow')) || 0,
        mid: Number(dynCacheForm.getFieldValue('l3PercentMid')) || 0,
        high: Number(dynCacheForm.getFieldValue('l3PercentHigh')) || 0,
      },
    } : {
      enable: false,
    };
    const psi = psiThreshold ? {
      enable: psiThreshold,
      resource: psiForm.getFieldValue('resource'),
      avg10Threshold: Number(psiForm.getFieldValue('avg10Threshold')) || 0,
    } : {
      enable: false,
    };
    const volcanoSchedulerConfig = {
      usagePlugin: {
        enable: volcanoCheck,
        usageThreshold: volcanoCheck && volcanoSchedulerForm.getFieldValue('enabledThreshold') ? {
          enable: volcanoSchedulerForm.getFieldValue('enabledThreshold'),
          cpu: Number(volcanoSchedulerForm.getFieldValue('cpuEvict')),
          memory: Number(volcanoSchedulerForm.getFieldValue('memoryEvict')),
        } : {
          enable: false,
        },
      },
    };

    const data = {
      nodeInfo: originalList,
      rubikConfig: { eviction, quotaTurbo, dynMemory, dynCache, psi },
      volcanoSchedulerConfig,
    };

    try {
      const res = await modifyNodeConfig(data);
      if (res.status === ResponseCode.OK) {
        messageApi.success('修改混部策略配置成功');
        setIsParamModalOpen(false);
        getConfigList();
      }
    } catch (e) {
      if (e) {
        messageApi.error(`修改混部策略配置失败`);
      }
    }
  };

  const updateModalForm = (configInfo) => {
    rubikForm.setFieldsValue(configInfo.rubikConfig.eviction.enable ? {
      enabledThreshold: configInfo.rubikConfig.eviction.enable,
      cpuEvict: String(configInfo.rubikConfig.eviction.cpuevict.threshold ?? '60'),
      memoryEvict: String(configInfo.rubikConfig.eviction.memoryevict.threshold ?? '60'),
    } : {
      enabledThreshold: configInfo.rubikConfig.eviction.enable,
      cpuEvict: '60',
      memoryEvict: '60',
    });
    setVolcanoCheck(configInfo.volcanoSchedulerConfig.usagePlugin.enable);
    volcanoSchedulerForm.setFieldsValue(configInfo.volcanoSchedulerConfig.usagePlugin.usageThreshold.enable ? {
      enabledThreshold: configInfo.volcanoSchedulerConfig.usagePlugin.usageThreshold.enable,
      cpuEvict: String(configInfo.volcanoSchedulerConfig.usagePlugin.usageThreshold.cpu ?? '60.0'),
      memoryEvict: String(configInfo.volcanoSchedulerConfig.usagePlugin.usageThreshold.memory ?? '60.0'),
    } : {
      enabledThreshold: configInfo.volcanoSchedulerConfig.usagePlugin.usageThreshold.enable,
      cpuEvict: '60.0',
      memoryEvict: '60.0',
    });
    quotaTurboForm.setFieldsValue(configInfo.rubikConfig.quotaTurbo.enable ?
      {
        enabledThreshold: configInfo.rubikConfig.quotaTurbo.enable ?? false,
        highWaterMark: String(configInfo.rubikConfig.quotaTurbo.highWaterMark ?? '60'),
        alarmWaterMark: String(configInfo.rubikConfig.quotaTurbo.alarmWaterMark ?? '60'),
      } : {
        enabledThreshold: configInfo.rubikConfig.quotaTurbo.enable ?? false,
        highWaterMark: '60',
        alarmWaterMark: '80',
      });
    dynMemoryForm.setFieldsValue({
      enabledThreshold: configInfo.rubikConfig.dynMemory.enable ?? false,
    });
    dynCacheForm.setFieldsValue(configInfo.rubikConfig.dynCache.enable ? {
      enabledThreshold: configInfo.rubikConfig.dynCache.enable ?? false,
      l3PercentLow: String(configInfo.rubikConfig.dynCache.l3Percent.low ?? '20'),
      l3PercentMid: String(configInfo.rubikConfig.dynCache.l3Percent.mid ?? '30'),
      l3PercentHigh: String(configInfo.rubikConfig.dynCache.l3Percent.high ?? '50'),
      memBandLow: String(configInfo.rubikConfig.dynCache.memBandPercent.low ?? '20'),
      memBandMid: String(configInfo.rubikConfig.dynCache.memBandPercent.mid ?? '30'),
      memBandHigh: String(configInfo.rubikConfig.dynCache.memBandPercent.high ?? '50'),
    } : {
      enabledThreshold: configInfo.rubikConfig.dynCache.enable ?? false,
      l3PercentLow: '20',
      l3PercentMid: '30',
      l3PercentHigh: '50',
      memBandLow: '20',
      memBandMid: '30',
      memBandHigh: '50',
    });
    psiForm.setFieldsValue(configInfo.rubikConfig.psi.enable ? {
      enabledThreshold: configInfo.rubikConfig.psi.enable ?? false,
      resource: configInfo.rubikConfig.psi.resource,
      avg10Threshold: String(configInfo.rubikConfig.psi.avg10Threshold ?? '5.0'),
    } : {
      enabledThreshold: configInfo.rubikConfig.psi.enable ?? false,
      resource: ['cpu', 'memory'],
      avg10Threshold: '5.0',
    });
  };

  // 关闭弹窗时清空未提交的配置
  useEffect(() => {
    if (!isParamModalOpen) {
      updateModalForm(colocationConfig);
    }
  }, [isParamModalOpen])

  const handleParamCancel = () => {
    setIsParamModalOpen(false);
  };

  const handleConfigTableChange =
    (
      pagination,
      filter,
      _sorter,
      extra,
    ) => {
      if (extra.action === 'paginate') {
        setConfigPage(pagination.page);
        setConfigPageSize(pagination.pageSize);
      }
      if (extra.action === 'filter') {
        setConfigPage(1);
      }
    };

  const getConfigList = useCallback(async (isChange = true) => {
    setConfigLoading(true);
    getNodeListData().then(res => {
      if (res.status === ResponseCode.OK) {
        setOriginalList(res.data.data.nodeInfo);
        let { rubikConfig, volcanoSchedulerConfig } = res.data.data;
        let colocationData = { rubikConfig, volcanoSchedulerConfig };
        setColocationConfig(colocationData);
        updateModalForm(colocationData);
        searchNode(res.data.data.nodeInfo, isChange); // 先搜索
      }
    }).catch(e => {
      setOriginalList([]);
      setConfigList([]); // 数组为空
      setColocationConfig({});
      if (e) {
        messageApi.error('数据获取失败');
      }
    }).finally(() => {
      setConfigLoading(false);
    });
  }, []);

  const validateInteger = (value, min, max) => {
    if (!value) {
      return Promise.reject(new Error('请输入数值'));
    }
    if (!/^[1-9]\d?$/.test(value)) {
      return Promise.reject(new Error(`请输入${min}-${max}之间的整数`));
    }
    let num = parseInt(value, 10);
    if (min && (num < min) || max && (num > max)) {
      return Promise.reject(new Error(`请输入${min}-${max}之间的整数`));
    }
    return Promise.resolve();
  };

  const validateFloat = (value, min, max, maxDigits) => {
    if (!value) {
      return Promise.reject(new Error('请输入数值'));
    }
    if (!/^\d*\.?\d+$/.test(value)) {
      return Promise.reject(new Error(`请输入${min}-${max}之间的浮点数`));
    }
    if (min && (value < min) || max && (value > max)) {
      return Promise.reject(new Error(`请输入${min}-${max}之间的浮点数`));
    }
    const [, decimalPart, ...resets] = value.split('.');
    if (decimalPart && decimalPart.length > maxDigits) {
      return Promise.reject(new Error(`最多${maxDigits}位小数`));
    }
    return Promise.resolve();
  };

  useEffect(() => {
    getConfigList();
  }, [getConfigList]);

  useEffect(() => {
    const newFilterStatus = [];
    Object.keys(nodeStatus).map(item => {
      newFilterStatus.push({ text: item, value: item });
    });
    setFilterNodeStatus(newFilterStatus);
  }, []);

  useEffect(() => {
    let quotaTurboFlag = false;
    let dynMemoryFlag = false;
    let dynCacheFlag = false;
    let psiDetectionFlag = false;
    let quotaTurboBadNodes = [];
    let dynMemoryBadNodes = [];
    let dynCacheBadNodes = [];
    let psiDetectionBadNodes = [];
    originalList.forEach(item => {
      if (item.isColocated) {
        if (item.featureSupport.quotaTurbo !== 'OK') {
          quotaTurboFlag = true;
          quotaTurboBadNodes.push(item.name);
        }
        if (item.featureSupport.dynMemory !== 'OK') {
          dynMemoryFlag = true;
          dynMemoryBadNodes.push(item.name);
        }
        if (item.featureSupport.dynCache !== 'OK') {
          dynCacheFlag = true;
          dynCacheBadNodes.push(item.name);
        }
        if (item.featureSupport.psiDetection !== 'OK') {
          psiDetectionFlag = true;
          psiDetectionBadNodes.push(item.name);
        }
      }
    });
    setQuotaTurboDisable(quotaTurboFlag);
    setDynmemoryDisable(dynMemoryFlag);
    setDyncacheDisable(dynCacheFlag);
    setPsiDisable(psiDetectionFlag);
    if (quotaTurboFlag) {
      setQuotaTurboDisableMsg('已启用混部的节点不支持该高级特性：' + quotaTurboBadNodes.join(', '));
    }
    if (dynMemoryFlag) {
      setDynmemoryDisableMsg('已启用混部的节点不支持该高级特性：' + dynMemoryBadNodes.join(', '));
    }
    if (dynCacheFlag) {
      setDyncacheDisableMsg('已启用混部的节点不支持该高级特性：' + dynCacheBadNodes.join(', '));
    }
    if (psiDetectionFlag) {
      setPsiDisableMsg('已启用混部的节点不支持该高级特性：' + psiDetectionBadNodes.join(', '));
    }
  }, [originalList]);

  return <div className="child_content">
    <BreadCrumbCom className="create_bread" items={[
      { title: '在离线混部', path: `/ColocationConfiguration` },
      { title: '混部策略配置', path: `/` },
    ]} />
    <div className="workload_content hybrid_detail_content_box">
      <div className='workload_detail_content'>
        <div className={`${isShow}`} style={{ marginTop: '20px' }}>
          <ToolTipComponent>
            <div className="podDetail" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div className='promot-box'>混部应用只能部署在混部节点上</div>
              <CloseOutlined onClick={handleConfigShowChange} />
            </div>
          </ToolTipComponent>
        </div>
        <div className={`${isShow}workload_detail_content_box`}>
          <div className='workload_detail_form'>
            <Form className="workload-searchForm form_padding_bottom" form={configForm}>
              <div className='workload-searchForm-box'>
                <Form.Item name="nodeConfigName" className="workload-search-input" style={{ marginRight: '20px' }}>
                  <Input.Search placeholder="搜索节点" onSearch={() => searchNode()} autoComplete="off" maxLength={53} />
                </Form.Item>
              </div>
              <Form.Item>
                <Space>
                  <Button className='workload_detail_form_button' onClick={handleOpenParamModal}>
                    混部策略参数配置
                  </Button>
                  <Button icon={<SyncOutlined />} onClick={handleRerfesh} className="reset_btn" style={{ marginLeft: '16px' }}></Button>
                </Space>
              </Form.Item>
            </Form>
          </div>
          <div className={`workLoad-colocation-table-no-padding workload_detail_content_table`}>
            {contextHolder}
            <ConfigProvider locale={zhCN}>
              <Table
                rowKey="name"
                scroll={{ y: 720 }}
                loading={configLoading}
                columns={configColumns}
                dataSource={configList}
                expandable={{
                  expandedRowRender: (record) => <div className="feature-support">
                    <p className="feature-support-line">必要特性：
                      <FeatureTag label="cpuPreemption" value={record.featureSupport.cpuPreemption} />
                      <FeatureTag label="memoryPreemption" value={record.featureSupport.memoryPreemption} />
                    </p>
                    <p className="feature-support-line">高级特性：
                      <FeatureTag label="quotaTurbo" value={record.featureSupport.quotaTurbo} />
                      <FeatureTag label="dynMemory" value={record.featureSupport.dynMemory} />
                      <FeatureTag label="psiDetection" value={record.featureSupport.psiDetection} />
                      <FeatureTag label="dynCache" value={record.featureSupport.dynCache} />
                    </p>
                  </div>,
                }}
                pagination={{
                  className: 'colocation-website-page',
                  current: configPage,
                  pageSize: configPageSize,
                  showTotal: (total) => `共${total}条`,
                  showSizeChanger: true,
                  showQuickJumper: true,
                  pageSizeOptions: [10, 20, 50],
                }}
                onChange={handleConfigTableChange}
              >
              </Table>
            </ConfigProvider>
          </div>
        </div>
      </div>
    </div>
    {/* 混部配置策略表单 */}
    <Modal
      className='modal_flex_colocation modal_set_config'
      width="1120px"
      height="720px"
      open={isParamModalOpen}
      title={<p>混部策略参数配置  <Popover color="#333333"
        placement="top"
        content={
          <p style={{ color: '#fff', margin: 0 }}>此配置会做用到全部开启混部功能的节点上，暂不支持对每个混部节点的特异性配置
          </p>
        }
        trigger='click'>
        <QuestionCircleOutlined />
      </Popover></p>
      }
      destroyOnHidden={true}
      getContainer={() => document.getElementsByClassName('hybrid_detail_content_box')[0]}
      transitionName=''
      maskTransitionName=''
      onCancel={handleParamCancel}
      footer={
        [
          <div className='modal_flex_colocation_bottom' style={{ justifyContent: 'flex-end' }}>
            <Button className='back_cancel_btn' onClick={handleParamCancel}>取消</Button>
            <Button className={'back_config_btn'} onClick={handleParamOk}>确定</Button>
          </div>,
        ]
      }
    >
      <div className='modal_config_box'>
        <div className='deployment_scheduling_box'>
          <div className='deployment_header'>
            <span className='title'>负载感知调度</span>
            <Popover color="#333333"
              placement="top"
              content={
                <p style={{ color: '#fff', margin: 0 }}>openFuyao感知集群节点CPU、Memory的负载情况，将Pod优先调度到负载较低的节点，实现节点负载均衡，避免出现因单个节点负载过高而导致的应用程序或节点故障
                </p>
              }
              trigger='click'>
              <QuestionCircleOutlined />
            </Popover>
            <Switch
              value={volcanoCheck}
              onChange={(checked) => setVolcanoCheck(checked)}
            />
          </div>
          {volcanoCheck && <div className='deployment_content'>
            <Form
              form={volcanoSchedulerForm}
              autoComplete="off"
            >
              <>
                <Form.Item colon={false} label="真实负载调度阈值开关" name="enabledThreshold" className='special_font_size'
                  style={{ display: 'block' }}>
                  <Switch />
                </Form.Item>
                <Form.Item noStyle shouldUpdate={(prevValues, currentValues) =>
                  prevValues.enabledThreshold !== currentValues.enabledThreshold
                }>
                  {({ getFieldValue }) =>
                    getFieldValue('enabledThreshold') && (
                      <>
                        <Form.Item
                          rules={[
                            { required: true, message: '' },
                            { validator: (_, value) => validateFloat(value, 0, 100, 2) }]}
                          colon={false}
                          label="节点CPU真实负载调度阈值（%）"
                          name="cpuEvict"
                          extra="节点在线业务的CPU真实利用率超过该阈值后，新下发的工作负载将不会被调度到当前节点，节点中已经运行的工作负载不受影响"
                          initialValue="60"
                        >
                          <Input placeholder='请输入0~100' />
                        </Form.Item>
                        <Form.Item rules={[
                          { required: true, message: '' },
                          { validator: (_, value) => validateFloat(value, 0, 100, 2) }]}
                          colon={false}
                          label="节点内存真实负载调度阈值（%）"
                          name="memoryEvict"
                          extra="节点在线业务的内存真实利用率超过该阈值后，新下发的工作负载将不会被调度到当前节点，节点中已经运行的工作负载不受影响"
                          initialValue="60"
                        >
                          <Input placeholder='请输入0~100' />
                        </Form.Item>
                      </>
                    )
                  }
                </Form.Item>
              </>
            </Form>
          </div>}
        </div>

        <div className='deployment_quotaTurbo' style={{ marginTop: '32px' }}>
          <Form
            form={quotaTurboForm}
            autoComplete="off"
          >
            <div className='deployment_header' style={{ flexDirection: 'row' }}>
              <span className='title'>CPU弹性限流</span>
              <Popover color="#333333"
                placement="top"
                content={
                  <p style={{ background: '#333333', color: '#fff', margin: 0 }}>
                    通过Linux内核提供的CFS bandwidth control能力实现，在保障整机负载水位安全稳定及不影响其他业务运行的前提下，通过双水位机制允许业务容器自适应调整CPU限制，缓解CPU资源瓶颈，提高业务的运行性能
                  </p>
                }
                trigger='click'>
                <QuestionCircleOutlined />
              </Popover>
              <Form.Item colon={false} label="" name="enabledThreshold" className='special_font_size' style={{ marginBottom: 0 }}>
                <DisabledTipSwitch disabled={quotaTurboDisable} disableMsg={quotaTurboDisableMsg} />
              </Form.Item>
            </div>
            <Form.Item noStyle shouldUpdate={(prevValues, currentValues) =>
              prevValues.enabledThreshold !== currentValues.enabledThreshold
            }>
              {({ getFieldValue }) => getFieldValue('enabledThreshold') && <div className='deployment_content'>
                <Form.Item rules={[
                  { required: true, message: '' },
                  {
                    validator: (_, value) => validateInteger(value, 0, 100),
                  }]
                }
                  colon={false}
                  label="CPU负载高水位"
                  name="highWaterMark"
                  extra="节点的CPU真实利用率超过该阈值后，新下发的工作负载将不会被调度到当前节点，节点中已经运行的工作负载不受影响"
                  initialValue="60"
                >
                  <Input placeholder='请输入0~100' />
                </Form.Item>
                <Form.Item rules={[
                  { required: true, message: '' },
                  {
                    validator: (_, value) => validateInteger(value, 0, 100),
                  }]}
                  colon={false}
                  label="CPU负载警戒水位"
                  name="alarmWaterMark"
                  extra={`混部引擎根据整机CPU实际负载情况与高水位/警戒水位的高低关系决定对开启quotaTurbo的pod的Quota的配置：
1.整机CPU负载高于警戒水位，则所有实际Quota超过配置的limit值的开启quotaTurbo的pod均会被快速回调Quota至limit值；
2.整机CPU负载低于警戒水位，则所有开启quotaTurbo且当周期内CPU收到压制的pod会被缓慢提升Quota高于配置的limit值；
3.整机CPU负载高于高水位，同时开启quotaTurbo的pod当周期CPU未收到压制，则该pod会被慢速回调直至limit值`}
                  initialValue="80"
                  style={{ whiteSpace: 'pre-wrap' }}
                >
                  <Input placeholder='请输入0~100' />
                </Form.Item>
              </div>}
            </Form.Item>
          </Form>
        </div>
        <div className='deployment_dynmemory' style={{ marginTop: '32px' }}>
          <Form
            form={dynMemoryForm}
            autoComplete="off"
          >
            <div className='deployment_header' style={{ flexDirection: 'row' }}>
              <span className='title'>内存异步分级回收</span>
              <Popover color="#333333"
                placement="top"
                content={
                  <p style={{ background: '#333333', color: '#fff', margin: 0 }}>
                    基于内核cgroup的动态水位线快压制慢恢复策略在整机内存使用量较高时，在后台异步回收离线容器的内存，不阻塞在线业务；在整机内存使用量较低时慢速提升离线容器的内存
                  </p>
                }
                trigger='click'>
                <QuestionCircleOutlined />
              </Popover>
              <Form.Item colon={false} label="" name="enabledThreshold" className='special_font_size' style={{ marginBottom: 0 }}>
                <DisabledTipSwitch disabled={dynMemoryDisable} disableMsg={dynMemoryDisableMsg} />
              </Form.Item>
            </div>
          </Form>
        </div>
        <div className='deployment_dyncache' style={{ marginTop: '32px' }}>
          <Form
            form={dynCacheForm}
            autoComplete="off"
          >
            <div className='deployment_header' style={{ flexDirection: 'row' }}>
              <span className='title'>访存带宽和L3 Cache限制</span>
              <Popover color="#333333"
                placement="top"
                content={
                  <p style={{ background: '#333333', color: '#fff', margin: 0 }}>
                    通过限制离线业务的访存宽带L3Cache的使用，减少其对在线业务的干扰
                  </p>
                }
                trigger='click'>
                <QuestionCircleOutlined />
              </Popover>
              <Form.Item colon={false} label="" name="enabledThreshold" className='special_font_size' style={{ marginBottom: 0 }}>
                <DisabledTipSwitch disabled={dynCacheDisable} disableMsg={dynCacheDisableMsg} />
              </Form.Item>
            </div>
            <Form.Item noStyle shouldUpdate={(prevValues, currentValues) =>
              prevValues.enabledThreshold !== currentValues.enabledThreshold
            } >
              {({ getFieldValue }) => getFieldValue('enabledThreshold') && <div className='deployment_content'>
                <p className='dyncache-label'>访存带宽水位线</p>
                <Form.Item
                  colon={false}
                  extra={`分别代表对离线业务访存带宽的不同限制程度，例如当低：20%，中：30%，高：50%，代表混部引擎会根据实际在线业务Pod的cache miss指标动态地限制离线Pod只能使用20%、30%、50%的访存带宽`}
                >
                  <Form.Item rules={[
                    { required: true, message: '' },
                    {
                      validator: (_, value) => validateInteger(value, 0, 100),
                    }]
                  }
                    colon={false}
                    label="低"
                    name="memBandLow"
                    initialValue={20}
                  >
                    <Input placeholder='请输入0~100' />
                  </Form.Item>
                  <Form.Item rules={[
                    { required: true, message: '' },
                    {
                      validator: (_, value) => validateInteger(value, 0, 100),
                    }]
                  }
                    colon={false}
                    label="中"
                    name="memBandMid"
                    initialValue={30}
                  >
                    <Input placeholder='请输入0~100' />
                  </Form.Item>
                  <Form.Item rules={[
                    { required: true, message: '' },
                    {
                      validator: (_, value) => validateInteger(value, 0, 100),
                    }]
                  }
                    colon={false}
                    label="高"
                    name="memBandHigh"
                    initialValue={50}
                  >
                    <Input placeholder='请输入0~100' />
                  </Form.Item>
                </Form.Item>
                <p className='dyncache-label'>L3Cache水位线</p>
                <Form.Item
                  colon={false}
                  extra={`分别代表对离线业务L3Cache的不同限制程度，例如当低：20%，中：30%，高：50%，代表混部引擎会根据实际在线业务Pod的L3 miss指标动态地限制离线Pod只能使用20%、30%、50%的L3 Cache`}
                >
                  <Form.Item rules={[
                    { required: true, message: '' },
                    {
                      validator: (_, value) => validateInteger(value, 0, 100),
                    }]
                  }
                    colon={false}
                    label="低"
                    name="l3PercentLow"
                    initialValue={20}
                  >
                    <Input placeholder='请输入0~100' />
                  </Form.Item>
                  <Form.Item rules={[
                    { required: true, message: '' },
                    {
                      validator: (_, value) => validateInteger(value, 0, 100),
                    }]
                  }
                    colon={false}
                    label="中"
                    name="l3PercentMid"
                    initialValue={30}
                  >
                    <Input placeholder='请输入0~100' />
                  </Form.Item>
                  <Form.Item rules={[
                    { required: true, message: '' },
                    {
                      validator: (_, value) => validateInteger(value, 0, 100),
                    }]
                  }
                    colon={false}
                    label="高"
                    name="l3PercentHigh"
                    initialValue={50}
                  >
                    <Input placeholder='请输入0~100' />
                  </Form.Item>
                </Form.Item>
              </div>}
            </Form.Item>
          </Form>
        </div>
        <div className='deployment_psi' style={{ marginTop: '32px' }}>
          <Form
            form={psiForm}
            autoComplete="off"
          >
            <div className='deployment_header' style={{ flexDirection: 'row' }}>
              <span className='title'>基于PSI指标的驱逐</span>
              <Popover color="#333333"
                placement="top"
                content={
                  <p style={{ background: '#333333', color: '#fff', margin: 0 }}>
                    通过感知在线Pod的PSI指标（CPU、内存、IO的some avg10 指标，表示任一在线Pod在10s内的平均阻塞时间比），当任一干扰指标到达阈值时，按策略驱逐离线Pod
                  </p>
                }
                trigger='click'>
                <QuestionCircleOutlined />
              </Popover>
              <Form.Item colon={false} label="" name="enabledThreshold" className='special_font_size' style={{ marginBottom: 0 }}>
                <DisabledTipSwitch disabled={psiDisable} disableMsg={psiDisableMsg} />
              </Form.Item>
            </div>
            <Form.Item noStyle shouldUpdate={(prevValues, currentValues) =>
              prevValues.enabledThreshold !== currentValues.enabledThreshold
            }>
              {({ getFieldValue }) => getFieldValue('enabledThreshold') && <div className='deployment_content'>
                <Form.Item
                  colon={false}
                  label="检测资源类型"
                  name="resource"
                >
                  <Checkbox.Group defaultValue={['cpu', 'memory']}>
                    <Row>
                      <Col>
                        <Checkbox value="cpu" style={{ lineHeight: '32px' }}>
                          CPU
                        </Checkbox>
                      </Col>
                      <Col>
                        <Checkbox value="memory" style={{ lineHeight: '32px' }}>
                          内存
                        </Checkbox>
                      </Col>
                      <Col>
                        <Checkbox value="io" style={{ lineHeight: '32px' }}>
                          IO
                        </Checkbox>
                      </Col>
                    </Row>
                  </Checkbox.Group>
                </Form.Item>
                <br />
                <Form.Item rules={[
                  { required: true, message: '' },
                  {
                    validator: (_, value) => validateFloat(value, 5, 100, 2),
                  }]
                }
                  colon={false}
                  label="干扰驱逐阈值"
                  name="avg10Threshold"
                  initialValue={5.0}
                  extra="用户可按需选择对CPU、内存、IO资源进行监测，并设置相应阈值若阻塞占比超过该阈值，则rubik按照一定策略驱逐离线Pod，释放相应资源若在线Pod的CPU和内存利用率偏高，rubik会驱逐当前占用CPU资源/内存资源最多的离线业务若离线业务I/O高，则会选择驱逐CPU资源占用最多的离线业务"
                >
                  <Input placeholder='请输入5.0~100.0' />
                </Form.Item>
              </div>}
            </Form.Item>
          </Form>
        </div>
        <div className='deployment_water_level_expulsion' style={{ marginTop: '32px' }}>
          <Form
            form={rubikForm}
            autoComplete="off"
          >
            <div className='deployment_header' style={{ flexDirection: 'row' }}>
              <span className='title'>离线负载水位线驱逐</span>
              <Form.Item colon={false} label="" name="enabledThreshold" className='special_font_size' style={{ marginLeft: '16px', marginBottom: 0 }}>
                <Switch />
              </Form.Item>
            </div>
            <Form.Item noStyle shouldUpdate={(prevValues, currentValues) =>
              prevValues.enabledThreshold !== currentValues.enabledThreshold
            }>
              {({ getFieldValue }) => getFieldValue('enabledThreshold') && <div className='deployment_content'>
                <Form.Item rules={[
                  { required: true, message: '' },
                  {
                    validator: (_, value) => validateInteger(value, 0, 100),
                  }]
                }
                  colon={false}
                  label="CPU驱逐水位线（%）"
                  name="cpuEvict"
                  extra="当节点上所有Pod的CPU真实使用率超过该阈值时，触发离线作业驱逐，直至恢复到水位线以下"
                  initialValue="60"
                >
                  <Input placeholder='请输入0~100' />
                </Form.Item>
                <Form.Item rules={[
                  { required: true, message: '' },
                  {
                    validator: (_, value) => validateInteger(value, 0, 100),
                  }]}
                  colon={false}
                  label="内存驱逐水位线（%）"
                  name="memoryEvict"
                  extra="当节点上所有Pod的内存真实使用率超过该阈值时，触发离线作业驱逐，直至恢复到水位线以下"
                  initialValue="60"
                >
                  <Input placeholder='请输入0~100' />
                </Form.Item>
              </div>}
            </Form.Item>
          </Form>
        </div>
      </div>
    </Modal >
  </div >;
}